using System;
using System.Runtime.InteropServices;
using System.Security;

namespace FB.WinForms.Controls
{
	/// <summary>
	/// Provides static methods for sending the windows messages TB_SETBUTTONINFO.
	/// </summary>
	[SuppressUnmanagedCodeSecurity]
	public sealed class NativeMethods 
	{ 
		private const int WM_USER = 0x0400; 
		private const int TB_SETBUTTONINFO = WM_USER + 66; 

		/// <summary>
		/// This private constructor is used to hide the default public constructor
		/// automatically added by the compiler.
		/// </summary>
		private NativeMethods()
		{
		}

		/// <summary>
		/// A set of flags that indicate which members of <see cref="TBBUTTONINFO.dwMask"/> contain valid information.
		/// </summary>
		[Flags]
		internal enum ToolBarInfo : uint
		{
			TBIF_IMAGE   = 0x00000001,
			TBIF_TEXT    = 0x00000002,
			TBIF_STATE   = 0x00000004,
			TBIF_STYLE   = 0x00000008,
			TBIF_LPARAM  = 0x00000010,
			TBIF_COMMAND = 0x00000020,
			TBIF_SIZE    = 0x00000040,
			TBIF_BYINDEX = 0x80000000,
		}

		/// <summary>
		/// Contains information for a specific button in a toolbar.
		/// </summary>
		[StructLayout(LayoutKind.Sequential)] 
		internal struct TBBUTTONINFO 
		{ 
			/// <summary>
			/// Size of the structure, in bytes.
			/// </summary>
			internal uint cbSize; 

			/// <summary>
			/// Set of flags that indicate which members contain valid information.
			/// </summary>
			internal ToolBarInfo dwMask; 

			/// <summary>
			/// Command identifier of the button. 
			/// </summary>
			internal int idCommand; 

			/// <summary>
			/// Image index of the button.
			/// </summary>
			internal int iImage; 

			/// <summary>
			/// State flags of the button.
			/// </summary>
			internal byte fsState; 

			/// <summary>
			/// Style flags of the button.
			/// </summary>
			internal byte fsStyle; 

			/// <summary>
			/// Width of the button, in pixels.
			/// </summary>
			internal short cx; 

			/// <summary>
			/// Application-defined value associated with the button.
			/// </summary>
			internal UIntPtr lParam; 

			/// <summary>
			/// Address of a character buffer that contains or receives the button text.
			/// </summary>
			[MarshalAs(UnmanagedType.LPTStr)] 
			internal string lpszText; 

			/// <summary>
			/// Size of the buffer at pszText.
			/// </summary>
			internal int cchText; 
		} 

		/// <summary>
		/// An overloaded <c>SendMessage</c> for sending a TB_SETBUTTONINFO message.
		/// </summary>
		/// <param name="hWnd">The handle of the ToolBar.</param>
		/// <param name="Msg">TB_SETBUTTONINFO</param>
		/// <param name="wParam">The index to the ToolBarButton.</param>
		/// <param name="lParam">Pointer to a <see cref="TBBUTTONINFO"/> structure that contains the new button information.</param>
		/// <returns>Returns nonzero if successful, or zero otherwise.</returns>
		[DllImport("user32.dll", SetLastError=true)]
		private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, ref TBBUTTONINFO lParam); 

		/// <summary>
		/// Sets the <see cref="System.Windows.Forms.ToolBarButton"/> specified by <paramref name="index"/> to the width specified by <paramref name="width"/>
		/// </summary>
		/// <param name="hwnd">The window handle that the <see cref="System.Windows.Forms.ToolBarButton"/> is bound to.</param>
		/// <param name="index">The index of the <see cref="System.Windows.Forms.ToolBarButton"/>.</param>
		/// <param name="width">The width of the <see cref="System.Windows.Forms.ToolBarButton"/> in pixels.</param>
		public static void SetButtonSize(IntPtr hwnd, int index, short width) 
		{ 
			TBBUTTONINFO tbif = new TBBUTTONINFO(); 
			tbif.dwMask = (ToolBarInfo.TBIF_BYINDEX | ToolBarInfo.TBIF_SIZE); 
			tbif.cx = width; 
			tbif.cbSize = (uint)Marshal.SizeOf(tbif); 
			SendMessage(hwnd, TB_SETBUTTONINFO, (IntPtr)index, ref tbif); 
		} 
	} 
}
